/*
 * Copyright (C) 2017 The MoonLake Authors
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package com.minecraft.moonlake.legendaryweaponrel.weapons;

import com.minecraft.moonlake.legendaryweaponrel.weapons.armor.*;
import com.minecraft.moonlake.legendaryweaponrel.weapons.bow.HealBow;
import com.minecraft.moonlake.legendaryweaponrel.weapons.bow.Rain;
import com.minecraft.moonlake.legendaryweaponrel.weapons.bow.SlowBow;
import com.minecraft.moonlake.legendaryweaponrel.weapons.bow.VoidBow;
import com.minecraft.moonlake.legendaryweaponrel.weapons.potion.Hail;
import com.minecraft.moonlake.legendaryweaponrel.weapons.potion.Might;
import com.minecraft.moonlake.legendaryweaponrel.weapons.potion.Tune;
import com.minecraft.moonlake.legendaryweaponrel.weapons.tool.*;
import com.minecraft.moonlake.util.StringUtil;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public final class Weapons {

    // Tool
    public final static Agni AGNI;
    public final static Deal DEAL;
    public final static Gamble GAMBLE;
    public final static LongSword LONGSWORD;
    public final static OverKill OVERKILL;
    public final static Sacrificial SACRIFICIAL;
    public final static Simon SIMON;
    public final static Storm STORM;
    public final static Vampyr VAMPYR;
    public final static NinjaSandals NINJASANDALS;
    public final static ThieveSword THIEVESWORD;
    ///

    // Armor
    public final static Bind BIND;
    public final static Tempest TEMPEST;
    public final static Terror TERROR;
    public final static Wrath WRATH;
    public final static RubberShield RUBBERSHIELD;
    ///

    // Bow
    public final static Rain RAIN;
    public final static SlowBow SLOWBOW;
    public final static HealBow HEALBOW;
    public final static VoidBow VOIDBOW;
    ///

    // Potion
    public final static Hail HAIL;
    public final static Might MIGHT;
    public final static Tune TUNE;

    private final static Map<Class<? extends Weapon>, Weapon> WEAPON_MAP;

    static {
        // 初始化武器
        WEAPON_MAP = new HashMap<>();

        // Tool
        WEAPON_MAP.put(Agni.class, AGNI = new Agni());
        WEAPON_MAP.put(Deal.class, DEAL = new Deal());
        WEAPON_MAP.put(Gamble.class, GAMBLE = new Gamble());
        WEAPON_MAP.put(OverKill.class, OVERKILL = new OverKill());
        WEAPON_MAP.put(Simon.class, SIMON = new Simon());
        WEAPON_MAP.put(Storm.class, STORM = new Storm());
        WEAPON_MAP.put(Vampyr.class, VAMPYR = new Vampyr());
        WEAPON_MAP.put(Sacrificial.class, SACRIFICIAL = new Sacrificial());
        WEAPON_MAP.put(LongSword.class, LONGSWORD = new LongSword());
        WEAPON_MAP.put(NinjaSandals.class, NINJASANDALS = new NinjaSandals());
        WEAPON_MAP.put(ThieveSword.class, THIEVESWORD = new ThieveSword());

        // Armor
        WEAPON_MAP.put(Bind.class, BIND = new Bind());
        WEAPON_MAP.put(Tempest.class, TEMPEST = new Tempest());
        WEAPON_MAP.put(Terror.class, TERROR = new Terror());
        WEAPON_MAP.put(Wrath.class, WRATH = new Wrath());
        WEAPON_MAP.put(RubberShield.class, RUBBERSHIELD = new RubberShield());

        // Bow
        WEAPON_MAP.put(Rain.class, RAIN = new Rain());
        WEAPON_MAP.put(SlowBow.class, SLOWBOW = new SlowBow());
        WEAPON_MAP.put(HealBow.class, HEALBOW = new HealBow());
        WEAPON_MAP.put(VoidBow.class, VOIDBOW = new VoidBow());

        // Potion
        WEAPON_MAP.put(Hail.class, HAIL = new Hail());
        WEAPON_MAP.put(Might.class, MIGHT = new Might());
        WEAPON_MAP.put(Tune.class, TUNE = new Tune());
    }

    public static Weapon[] values() {
        // 获取武器数组对象
        Collection<Weapon> values = WEAPON_MAP.values();
        return values.toArray(new Weapon[values.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Weapon> T getWeapon(Class<T> clazz, Player player, ItemStack handItem) {
        // 获取指定武器类的对象并判断玩家的手持武器
        if(clazz == null || player == null) return null;
        if(handItem == null || handItem.getType() == Material.AIR) return null;
        if(!handItem.hasItemMeta() || !handItem.getItemMeta().hasDisplayName()) return null;
        // 获取武器对象
        Weapon weapon = WEAPON_MAP.get(clazz);
        if(weapon == null) return null;
        // 判断类型和名称是否符合
        if(!compareWeapon(handItem, weapon)) return null;
        // 都符合则返回对象
        return (T) weapon;
    }

    @SuppressWarnings("unchecked")
    public static <T extends WeaponArmor> T getWeaponArmor(Player player, ItemStack handItem) {
        // 获取指定玩家的手持物品是否为传说武器护甲则返回对象, 否则 null
        if(player == null) return null;
        if(handItem == null || handItem.getType() == Material.AIR) return null;
        if(!handItem.hasItemMeta() || !handItem.getItemMeta().hasDisplayName()) return null;

        WeaponArmor result = null;

        // 判断是否传说武器护甲
        if(compareWeapon(handItem, BIND)) result = BIND;
        else if(compareWeapon(handItem, TEMPEST)) result = TEMPEST;
        else if(compareWeapon(handItem, TERROR)) result = TERROR;
        else if(compareWeapon(handItem, WRATH)) result = WRATH;
        else if(compareWeapon(handItem, NINJASANDALS)) result = NINJASANDALS;
        else if(compareWeapon(handItem, RUBBERSHIELD)) result = RUBBERSHIELD;

        return result == null ? null : (T) result;
    }

    public static boolean isWeaponArmor(Player player, ItemStack handItem) {
        // 获取指定玩家的手持物品是否为传送武器
        return getWeaponArmor(player, handItem) != null;
    }

    private static boolean compareWeapon(ItemStack handItem, Weapon weapon) {
        // 对比指定物品是否符合指定传说武器的名称
        return handItem.getType() == weapon.getMaterial() && handItem.getItemMeta().getDisplayName().equals(StringUtil.toColor(weapon.getDisplayName()));
    }
}
